from random import sample

from django.db.models import Q
from django.shortcuts import render

# Create your views here.
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated
from work.models import Label, Topic
from work.serializers import LabelSerializer, TopicSerializer, TopicStudentSerializer
from utils.permission import *
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination
from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_404_NOT_FOUND
from elasticsearch import Elasticsearch
from config.elasticSearchConfig import *

# 创建ES客户端对象，链接ES服务
es = Elasticsearch([{'host': HOST,'port': PORT}])

# class TopicPageNumberPagination(PageNumberPagination):
#     page_size = 3  # 默认每页多少条数据
#     page_size_query_param = 'size'  # 规定哪个参数作为分页大小的参数 s = 5
#     max_page_size = 100  # 最大每页多少条数据

class TopicLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 3  # 默认每页多少条数据
    max_limit = 100  # 最大每页多少条数据


class LabelViewSet(ModelViewSet):
    queryset = Label.objects.all()
    serializer_class = LabelSerializer
    permission_classes = [IsAuthenticated]

    @wrap_permission(TeacherPermission)
    @auto_user
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @wrap_permission(ActiveUserPPermission)
    @auto_user
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @wrap_permission(RootPermission)
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)


class TopicViewSet(ModelViewSet):
    queryset = Topic.objects.filter(is_delete=False)
    serializer_class = TopicSerializer
    permission_classes = [IsAuthenticated]

    pagination_class = TopicLimitOffsetPagination

    def get_queryset(self):
        if self.action in ['practice', 'random']:
            return Topic.objects.filter(Q(is_delete=False) & ~Q(label__name__contains='试卷'))
        return self.queryset

    def get_serializer(self, *args, **kwargs):
        if self.action in ['exam', 'random']:
            return TopicStudentSerializer(*args, **kwargs)
        return self.serializer_class(*args, **kwargs)

    @wrap_permission(TeacherPermission)
    def list(self, request, *args, **kwargs):
        return ModelViewSet.list(self, request, *args, **kwargs)

    @wrap_permission(TeacherPermission)
    def retrieve(self, request, *args, **kwargs):
        return ModelViewSet.retrieve(self, request, *args, **kwargs)

    @action(methods=['get'], detail=False)
    def practice(self, request):
        return ModelViewSet.list(self, request)

    @action(methods=['get'], detail=False)
    def random(self, request):
        # 获取随机刷题的题目个数
        try:
            size = int(request.query_params.get('size', 3))
        except ValueError:
            return Response(status=HTTP_400_BAD_REQUEST)

        # 获取查询集，随机抽取指定个数
        pool = list(self.get_queryset())
        # 判断要获取的随机题目个数是否超过题目总数，如果超过则给出提示
        if len(pool) < size:
            return Response({'detail': '超出题目个数，题目总数为:%s'%len(pool)})

        # 序列化，返回
        serializer = self.get_serializer(sample(pool, size), many=True)
        return Response(serializer.data)

    @action(methods=['get'], detail=True)
    def exam(self, request, pk):
        # 获取指定标签， 指定试卷
        labels = Label.objects.filter(id=pk, name__contains='试卷').first()
        # 判断有没有这个试卷，没有返回404
        if not labels:
            return Response(status=HTTP_404_NOT_FOUND)
        # 有试卷，获取这个试卷所有的题目，不包含答案
        topics = labels.topic_set.filter(is_delete=False)
        serializer = self.get_serializer(topics, many=True)
        return Response(serializer.data)

    @action(methods=['put'], detail=False)
    def inites(self, request):
        # 获取mysql中所有的题目数据
        serializer = self.get_serializer(self.get_queryset(), many=True)
        data = serializer.data
        # 保存插入到es当中
        for i in data:
            es.index(index='topic', id=i['id'], body=i)  # 索引，指定id插入数据， body数据
        return Response(data)

    @action(methods=['get'], detail=False)
    def search(self, request):
        # 获取前端传入的数据
        data = dict(request.query_params)
        offset = int(data.get('offset', [0])[0])
        limit = int(data.get('limit', [3])[0])
        subject = data.get('subject', [""])[0]

        # 判断用户身份
        user = request.user  # 当前发起请求的用户
        # 判断身份，查询是否在老师分组
        gourp = Group.objects.filter(name='老师').first()
        user_groups = user.groups.all()
        work_user = user.is_superuser or gourp in user_groups

        query = {
            "query": {

            },
            "highlight": {
                "pre_tags": "<span style='color:red'>",
                "post_tags": "</span>",
                "fields": {
                    "subject": {}
                }
            },
            "from": offset,
            "size": limit
        }

        if work_user:
            # 老师或者管理员
            if subject:
                query["query"]["match"] = {
                    "subject": subject
                }
            else:
                query["query"]["match_all"] = {}
        else:
            # 学生 有关键字查询
            if subject:
                query['query'] = {
                    "bool": {
                        "must": [{
                            "match": {
                                "subject": subject
                            }
                        }],
                        "must_not": [{
                            "match_phrase": {
                                "label_name": "试题"
                            }
                        }]
                    }
                }
            else:
                # 学生直接查询
                query['query'] = {
                    "bool": {
                        "must_not": [{
                            "match_phrase": {
                                "label_name": "试题"
                            }
                        }]
                    }
                }
        es_res = es.search(index='topic', body=query)
        count = es_res['hits']['total']['value']
        subject_url = f'subject={subject}&' if subject else ''
        next = f'{CLIENT}/work/topics/search?{subject_url}limit={limit}&offset={offset + limit}' if offset + limit < count else None
        previous = f'{CLIENT}/work/topics/search?{subject_url}limit={limit}&offset={offset - limit}' if offset > 0 else None
        results = [self.highlight(i) for i in es_res['hits']['hits']]
        res = {
            "count": count,
            "next": next,
            "previous": previous,
            "results": results
        }

        return Response(res)

    def highlight(self, i):
        if i.get('highlight'):
            i['_source']['subject'] = i['highlight']['subject']
        return i['_source']
